package com.gcb.common.utils.huawei;

import lombok.extern.slf4j.Slf4j;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 华为短信一
 *
 */
@Slf4j
public class SmsUtils {

    //无需修改,用于格式化鉴权头域,给"X-WSSE"参数赋值
    private static final String WSSE_HEADER_FORMAT = "UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\"";
    //无需修改,用于格式化鉴权头域,给"Authorization"参数赋值
    private static final String AUTH_HEADER_VALUE = "WSSE realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"";

    //必填,请参考"开发准备"获取如下数据,替换为实际值
    private static final String url = "https://smsapi.cn-south-1.myhuaweicloud.com:443/sms/batchSendSms/v1"; //APP接入地址(在控制台"应用管理"页面获取)+接口访问URI
    private static final String appKey = "qnN2YQnn3YzQLD6Yt8lYo34X7BH6"; //APP_Key
    private static final String appSecret = "QQ5CDD9ppzBRZLTGKoBOIKlq7INI"; //APP_Secret

    //正式环境
    private static final String sender = "8824032723297";  //短信通道号
    //模板ID 目前是测试短信的ID，后续修改成申请的的模板ID
    // private static final String templateId = "1ab4bc87aed2465d8916870e6d410c90";
    private static final String templateId = "96d58915d4464b69bd5740425fd26415";
    //签名名称目前是测试短信的签名，后续修改成申请的的签名
    private static final String signature = "工船宝";
    //选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告
    private static final String statusCallBack = "";

    private static final String senderNotify = "8824011135902";  //短信通道号
    //模板ID 目前是测试短信的ID，后续修改成申请的的模板ID
    private static final String templateIdNotify = "23917b21bd984158ae165efdbc6ef049";
    //签名名称目前是测试短信的签名，后续修改成申请的的签名
    private static final String signatureNotify = "工船宝";



    /**
     * <H1>验证码短信发送</H1>
     *
     * @param templateParas 验证码
     * @param receiver      接收人手机号
     * @return void
     */
    public static int sendSms(String templateParas, String receiver) throws Exception {
        return sendRequest(templateParas,receiver,SmsUtils.sender,SmsUtils.templateId,SmsUtils.signature);
    }

    /**
     *  发送请求
     * @param templateParas 发送内容
     * @param receiver 手机号
     * @param sender 通道号
     * @param templateId 模板ID
     * @param signature 签名
     * @return 结果
     * @throws Exception 异常
     */
    public static int sendRequest(String templateParas, String receiver,String sender,String templateId,
                                  String signature) throws Exception {
        int status = 500;
        //请求Body,不携带签名名称时,signature请填null
        String body = buildRequestBody(receiver, templateParas,sender,templateId,signature);
        if (null == body || body.isEmpty()) {
            log.error("sendSms 发送短信异常: body is null.");
            return status;
        }

        //请求Headers中的X-WSSE参数值
        String wsseHeader = buildWsseHeader();
        if (null == wsseHeader || wsseHeader.isEmpty()) {
            log.error("sendSms 发送短信异常: wsse header is null.");
            return status;
        }

        Writer out = null;
        BufferedReader in = null;
        StringBuffer result = new StringBuffer();
        HttpsURLConnection connection;
        InputStream is = null;


        HostnameVerifier hv = (hostname, session) -> true;
        trustAllHttpsCertificates();

        try {
            URL realUrl = new URL(url);
            connection = (HttpsURLConnection) realUrl.openConnection();

            connection.setHostnameVerifier(hv);
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(true);
            //请求方法
            connection.setRequestMethod("POST");
            //请求Headers参数
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            connection.setRequestProperty("Authorization", AUTH_HEADER_VALUE);
            connection.setRequestProperty("X-WSSE", wsseHeader);

            connection.connect();
            out = new OutputStreamWriter(connection.getOutputStream());
            out.write(body); //发送请求Body参数
            out.flush();
            out.close();
            status = connection.getResponseCode();
            if (200 == status) { //200
                is = connection.getInputStream();
            } else { //400/401
                is = connection.getErrorStream();
            }
            in = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
            log.info("sendSms 发送短信结束, 返回信息:{}", result);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != out) {
                    out.close();
                }
                if (null != is) {
                    is.close();
                }
                if (null != in) {
                    in.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return status;
    }

    /**
     *  创建请求体
     * @param receiver 接收人
     * @param templateParas 模板参数
     * @return
     */
    static String buildRequestBody(String receiver, String templateParas,String sender,String templateId,
                                   String signature) {
        if (null == receiver || receiver.isEmpty()) {
            log.error("buildRequestBody():发送方、接收方或templateId为空。");
            return null;
        }
        Map<String, String> map = new HashMap<>();
        map.put("from", sender);
        map.put("to", receiver);
        map.put("templateId", templateId);
        if (null != templateParas && !templateParas.isEmpty()) {
            map.put("templateParas", "[" + templateParas + "]");
        }
        map.put("signature", signature);

        StringBuilder sb = new StringBuilder();
        String temp = "";

        for (String s : map.keySet()) {
            try {
                temp = URLEncoder.encode(map.get(s), "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            sb.append(s).append("=").append(temp).append("&");
        }

        return sb.deleteCharAt(sb.length() - 1).toString();
    }

    /**
     * 构造X-WSSE参数值
     */
    static String buildWsseHeader() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        String time = sdf.format(new Date()); //Created
        String nonce = UUID.randomUUID().toString().replace("-", ""); //Nonce

        MessageDigest md;
        byte[] passwordDigest = null;

        try {
            md = MessageDigest.getInstance("SHA-256");
            md.update((nonce + time + SmsUtils.appSecret).getBytes());
            passwordDigest = md.digest();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        //如果JDK版本是1.8,请加载原生Base64类,并使用如下代码
        String passwordDigestBase64Str = Base64.getEncoder().encodeToString(passwordDigest); //PasswordDigest
        //如果JDK版本低于1.8,请加载三方库提供Base64类,并使用如下代码
        //String passwordDigestBase64Str = Base64.encodeBase64String(passwordDigest); //PasswordDigest
        //若passwordDigestBase64Str中包含换行符,请执行如下代码进行修正
        //passwordDigestBase64Str = passwordDigestBase64Str.replaceAll("[\\s*\t\n\r]", "");
        return String.format(WSSE_HEADER_FORMAT, SmsUtils.appKey, passwordDigestBase64Str, nonce, time);
    }

    /**
     * 信任https证书
     * @throws Exception
     */
    static void trustAllHttpsCertificates() throws Exception {
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        return;
                    }

                    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        return;
                    }

                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
                }
        };
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, null);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }


}
